package com.thiswhyme.common.utils.codec;

import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;

import java.nio.charset.StandardCharsets;
import java.security.Security;
import java.util.Arrays;

/**
 * @description: SM3加解密工具类
 * @author: thiswhyme
 * @date: 2021/4/14
 */
public class SM3Utils {

	static {
	  Security.addProvider(new BouncyCastleProvider());
	}

	/**
	* 签名（byte数组）
	* @explain 生成对应的hash值
	* @param srcData 原文
	* @return byte数组
	*/
	public static byte[] sign(byte[] srcData) {
	   SM3Digest digest = new SM3Digest();
	   digest.update(srcData, 0, srcData.length);
	   byte[] hash = new byte[digest.getDigestSize()];
	   digest.doFinal(hash, 0);
	   return hash;
	}

	/**
	 * 验签
	 * @param srcData 原文
	 * @param sm3Hash 摘要值
	 * @return 返回true标识验证成功，false标识验证失败
	 */
	public static boolean verify(byte[] srcData, byte[] sm3Hash) {
		byte[] newHash = sign(srcData);
		return Arrays.equals(newHash, sm3Hash);
	}

	/**
	 * 签名（16进制字符串）
	 * @param srcStr 原字符串
	 * @return 16进制字符串
	 */
	public static String signToHexString(String srcStr){
		String resultHexString;
		byte[] resultHash = sign(srcStr.getBytes(StandardCharsets.UTF_8));
		//转16进制字符串
		resultHexString = ByteUtils.toHexString(resultHash);
		return resultHexString;
	}

	/**
	 * 验签
	 * @param srcStr 原字符串
	 * @param sm3HexString 16进制字符串
	 * @return 校验结果
	 */
	public static boolean verifyFromHexString(String srcStr, String sm3HexString) {
		boolean result;
		byte[] srcData = srcStr.getBytes(StandardCharsets.UTF_8);
		byte[] sm3Hash = ByteUtils.fromHexString(sm3HexString);
		result = verify(srcData, sm3Hash);
		return result;
	}

	/**
	 * 签名（base64字符串）
	 * @param srcStr 原字符串
	 * @return Base64字符串
	 */
	public static String signToBase64String(String srcStr){
		String resultHexString;
		byte[] resultHash = sign(srcStr.getBytes(StandardCharsets.UTF_8));
		//转Base64字符串
		resultHexString = CodecUtils.bytes2Base64String(resultHash);
		return resultHexString;
	}

	/**
	 * 验签
	 * @param srcStr 原字符串
	 * @param sm3Base64String Base64字符串
	 * @return 校验结果
	 */
	public static boolean verifyFromBase64String(String srcStr, String sm3Base64String) {
		boolean result;
		byte[] srcData = srcStr.getBytes(StandardCharsets.UTF_8);
		byte[] sm3Hash = CodecUtils.base64String2Bytes(sm3Base64String);
		result = verify(srcData, sm3Hash);
		return result;
	}
}
